/**
 * @projectName: petJoyHome
 * @author: 小飞
 * @description: TODO
 * @date: 2024/3/1 15:42
 * @version: 1.0
 */
package com.home.config.securityConfig;

import com.home.filter.JwtTokenUserFilter;
import com.home.service.impl.UserDetailServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Collections;

@Configuration
@Slf4j
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final UserDetailServiceImpl userDetailService;

    private final JwtTokenUserFilter jwtTokenUserFilter;

    private final MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    private final MyAccessDeniedHandler myAccessDeniedHandler;

    //关于密码加密
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Primary
    @Bean
    public AuthenticationManager userAuthenticationManager() throws Exception {
        return new ProviderManager(Collections.singletonList(
                new DaoAuthenticationProvider() {{
                    setUserDetailsService(userDetailService);
                    setPasswordEncoder(passwordEncoder());
                }}
        ));
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                //关闭csrf(跨站请求伪造),防止csrf攻击
                .csrf().disable()
                //关闭session,设置会话创建策略为无状态（STATELESS），表示不会创建会话来存储用户信息，每个请求都需要进行认证授权操作。
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //表示开启对请求进行授权验证
                .authorizeRequests()
                //以下路径允许匿名访问，即不需要认证即可访问
                .antMatchers("/home/user/login").anonymous()
//                .antMatchers("/home/user/**").hasAnyAuthority("admin","super_admin")
                //以下静态资源
                .antMatchers("/favicon.ico",
                        "/error",
                        "/swagger-resources/**",
                        "/webjars/**",
                        "/v2/**",
                        "/doc.html",
                        "**/swagger-ui.html").permitAll()
                //其他路径全部都需要进行认证之后才能进行访问
                .anyRequest().authenticated();
        log.info("开始注册自定义过滤器.....");
        http.addFilterBefore(jwtTokenUserFilter, UsernamePasswordAuthenticationFilter.class);
        //未登录或者没权限返回信息
        http.exceptionHandling().authenticationEntryPoint(myAuthenticationEntryPoint).accessDeniedHandler(myAccessDeniedHandler);
        return http.build();
    }
}
